#include <time.h>
#include "webactivite.h"
#include "webcollector.h"
#include "webspideraround.h"
#include "../core/browser.h"
#include "../core/networkaccessmanager.h"

WebActivite::WebActivite(WebSpiderAround *spiderAround)
    : m_adapter(Browser::instance()->createWebPage(this, spiderAround->request()))
    , m_spiderAround(spiderAround)
    , m_url(spiderAround->requestUrl())
    , m_loadCanceledCount(0)
    , m_loadingProcess(0)
    , m_logger(Log4Qt::Logger::logger("WebActivite"))
    , m_hasLoadResource(0)
    , m_requestTs(time(NULL))
    , m_startTs(0)
{
}

WebActivite::~WebActivite()
{
    destoryWebPageAdapter();

    if (m_spiderAround) {
        delete m_spiderAround;
        m_spiderAround = NULL;
    }
}

Operator* WebActivite::startWithCompletedWebPage(WebPage *page)
{
    m_adapter = new WebPageAdapter(page, this, m_spiderAround->request());
    return m_adapter->opt();
}

void WebActivite::start()
{
    m_startTs = time(NULL);
    QString log = "openurl : " + m_url;
    m_logger->info(log);
    m_adapter->openUrl(m_url, QVariant(), Browser::instance()->defaultPageSettings(), m_spiderAround->request()->getCookies());
    log = "openurl : " + m_url + " end";
    m_logger->info(log);
}

void WebActivite::stop()
{
    m_adapter->stop();
}

QString WebActivite::url()
{
    QString u;

    if (m_url != "")
        u = m_url;
    else if (m_completelyUrl != "")
        u = m_completelyUrl;

    return u;
}

long WebActivite::ref()
{
    return (long) (m_adapter->opt());
}

std::string WebActivite::clientID()
{
    return m_adapter->opt()->clientID();
}

int WebActivite::loadingProcess()
{
    return m_loadingProcess;
}

void WebActivite::didLoadStart(Operator *opt)
{
    opt->startTimeoutTimer();
}

void WebActivite::didInitialized(Operator *opt)
{
    m_loadingProcess = opt->loadingProgress();
    opt->startTimeoutTimer();
}

void WebActivite::didLoadStarted(Operator *opt)
{
    QString logMessage = "WebActivite::didLoadStarted ( " + QString::number((long)opt) + " ), url: " + opt->getUrl();
    m_logger->info(logMessage);
    opt->startTimeoutTimer();
    m_hasLoadResource = 0;
    m_loadingProcess = opt->loadingProgress();
}

void WebActivite::didSelfDestroyParse(Operator* opt, QString & status)
{
    QString logMessage = "WebActivite::didLoadFinished ( " + status + " ) will be remove, url: " + opt->getUrl();
    m_logger->info(logMessage);
    m_spiderAround->remove(opt);
    opt->remove();
}

void WebActivite::didTimeout(Operator* opt, QString & status)
{
    QString logMessage = "WebActivite::didLoadFinished ( " + status + " ) porgress:" + QString::number(opt->loadingProgress()) + " url: " + opt->getUrl();
    m_logger->info(logMessage);

    // The page which called by get will be remove in webspider::parse() function
    if (!opt->hasParsed()) {
        opt->clearLoadSuccess();
        m_spiderAround->parse(opt);
        opt->setParsed();
        opt->startSelfDestroyTimer();
    }
}

void WebActivite::didLoadFinished(Operator *opt, const QString & status)
{
    m_loadingProcess = opt->loadingProgress();

    QString logMessage = "WebActivite::didLoadFinished ( " + status + " ) porgress:" + QString::number(opt->loadingProgress()) + " url: " + opt->getUrl();
    m_logger->info(logMessage);

    if (opt->isTimeout() || opt->hasParsed())
        return;

    opt->startSelfDestroyTimer();

    if (!opt->loading() && status == "success") {
        opt->setLoadSuccess();
        m_spiderAround->parse(opt);
        opt->setParsed();
    } else if (!opt->loading() && status == "fail") {
        opt->clearLoadSuccess();
        m_spiderAround->parse(opt);
        opt->setParsed();
        if (!opt->syncLoad()) {
            logMessage = "WebActivite::didLoadFinished ( " + status + " ) will be remove, url: " + opt->getUrl();
            m_logger->info(logMessage);
            opt->remove();
        }
        return;
    }

    if (opt->getUrl() == "about:blank" && status == "fail") {
        opt->clearLoadSuccess();
        m_spiderAround->parse(opt);
        opt->setParsed();
        logMessage = "WebActivite::didLoadFinished ( about:blank page -- " + status + " ) | url: " + opt->getUrl();
        m_logger->info(logMessage);
    }
}

void WebActivite::didJavaScriptAlertSent(Operator *opt, const QString & msg)
{
    m_loadingProcess = opt->loadingProgress();

    opt->setLastAlertString(msg);
}

void WebActivite::didJavaScriptConsoleMessageSent(Operator *opt, const QString & message)
{
    m_loadingProcess = opt->loadingProgress();

#if 0 
    QString logMessage = "[Console] url: " + opt->getUrl();
    m_logger->debug(logMessage);
    logMessage = "[Console] message: " + message;
    m_logger->debug(logMessage);
#endif
}

void WebActivite::didJavaScriptErrorSent(Operator *opt, const QString & msg, const QString & stack)
{
    m_loadingProcess = opt->loadingProgress();

#if 0 
    QString logMessage = "[JS Error] url: " + opt->getUrl();
    m_logger->debug(logMessage);
    logMessage = "[JS Error] msg: " + msg;
    m_logger->debug(logMessage);
    logMessage = "[JS Error] stack: " + stack;
    m_logger->debug(logMessage);
#endif
}

void WebActivite::didResourceRequested(Operator *opt, const QVariant & requestData, QObject * request)
{
    QVariantMap data = requestData.toMap();
    m_loadingProcess = opt->loadingProgress();

    // If has load resource is 0, it
    // may be main resource, save the
    // post data if method is post.
    if (!opt->hasParsed() && m_hasLoadResource == 0) {
        QString method = data["method"].toString();
        opt->setMethod(method);
        if (method == "POST")
            opt->setPostData(data["postData"].toString());
    }
    
    QString url = data["url"].toString();
    JsNetworkRequest *req = qobject_cast<JsNetworkRequest*>(request);

    // main resource cannot be cancelled.
    if (req && m_hasLoadResource != 0 && opt->matchFilter(url))
        req->abort();

    if (opt->getDownloadRequest()) {
        QVariantList headers = data["headers"].toList();
        m_urlHeadersMap.insert(url, headers);
    }

    m_hasLoadResource ++;
}

void WebActivite::didResourceReceived(Operator *opt, const QVariant & resource)
{
    m_loadingProcess = opt->loadingProgress();
    QVariantMap data = resource.toMap();
    QString url = data["url"].toString();
    
    if (opt->getDownloadRequest()) {
        QString contentType = data["contentType"].toString();
        if (contentType == opt->getDownloadRequest()->contentType()) {
            if (m_urlHeadersMap.contains(url)) {
                QVariantList headers = m_urlHeadersMap.value(url);
                opt->getDownloadRequest()->setHeaders(headers);
            }
            opt->getDownloadRequest()->setLink(url);
            opt->getDownloadRequest()->setSuccess();
            opt->getDownloadRequest()->end();
            m_urlHeadersMap.clear();
        }
    }
}

void WebActivite::didResourceError(Operator *opt, const QVariant & errorData)
{
    m_loadingProcess = opt->loadingProgress();

    QVariantMap data = errorData.toMap();

    int errorCode = data["errorCode"].toInt();
    bool isMainResource = false;

    if (data["url"] == opt->request()->url()
           || data["url"].toString() == opt->request()->url()+"/"
           || data["url"].toString() == opt->getUrl()
       )
        isMainResource = true;

    if (errorCode == 3 && isMainResource)
        opt->setHostNotFound();

    if (errorCode == 5 && isMainResource)
        opt->setHTTPRequestCanceled();

    if (errorCode == 99 && isMainResource)
        opt->setNetWorkError();

    if (errorCode == 301)
        opt->setProtocolUnknown();

    if (isMainResource)
        opt->setErrorCode(-errorCode);

    QString logMessage = "WebActivite::didResourceError( " + data["url"].toString() + " | " + QString::number(data["errorCode"].toInt()) + ") url: " + opt->getUrl();
    m_logger->info(logMessage);
}

void WebActivite::didResourceTimeout(Operator *opt, const QVariant & errorData)
{
    m_loadingProcess = opt->loadingProgress();
}

void WebActivite::didUrlChanged(Operator *opt, const QUrl & url)
{
    m_loadingProcess = opt->loadingProgress();
    m_completelyUrl = opt->getUrl();
}

void WebActivite::didNavigationRequested(Operator *opt, const QUrl & url, const QString & navigationType, bool navigationLocked, bool isMainFrame)
{
    m_loadingProcess = opt->loadingProgress();
}

void WebActivite::didRawPageCreated(Operator *opt, QObject * page)
{
    m_loadingProcess = opt->loadingProgress();

    if (m_spiderAround && !opt->hasParsed() && opt->loadingProgress() >= 100) {
        opt->setLoadSuccess();
        m_spiderAround->parse(opt);
        opt->setParsed();
    }

    QString logMessage = "WebActivite::didRawPageCreated( ) url: " + opt->getUrl();
    m_logger->info(logMessage);
}

void WebActivite::didClosing(Operator *opt, QObject * page)
{
    m_loadingProcess = opt->loadingProgress();
}

WebPageAdapter* WebActivite::webAdapter()
{
    return m_adapter;
}

void WebActivite::destoryWebPageAdapter()
{
    if (m_adapter)
        Browser::instance()->destoryWebPage(m_adapter);
    m_adapter = NULL;
}

int WebActivite::level()
{
    return m_spiderAround->request()->level();
}

